using System;
using System.Collections.Generic;
using System.Text;
using Mpi.Common;
using Mpi.Common.Collections;
using System.ComponentModel;
using Xeml.Document.Contracts;

namespace Xeml.Document
{
    public class StoryBoard : Tree<StoryBase>
    {
        
        private TimeSpan _observationTime;

        #region Properties
        /// <summary>
        /// The length of the hole observation time.
        /// </summary>
        public TimeSpan ObservationTime
        {
            get
            {
                return this._observationTime;
            }
            set
            {
                if (this._observationTime != value)
                {
                    TimeSpan old = this._observationTime;
                    this._observationTime = value;
                    //OnStructureChanged();
                    OnObservationTimeHasChanged(old);
                }
            }
        }

        private IDocument _owner;
        public IDocument Owner
        {
            get { return _owner; }
        } 
        #endregion

        #region ctor
        /// <summary>
        /// The standard constructor.
        /// </summary>
        public StoryBoard(IDocument owner)
        {
            _owner = owner;
            base.NodeAdded += new EventHandler<NodeEventArgs<StoryBase>>(OnStoryNodeAdded);
            base.NodeRemoved += new EventHandler<NodeEventArgs<StoryBase>>(OnStoryNodeRemoved);
        } 
        #endregion
      
        #region Event-/handling
        public event EventHandler Changed;
        public event EventHandler<ItemEventArgs<StoryBase>> StoryAdded;
        public event EventHandler<ItemEventArgs<StoryBase>> StoryRemoved;
        public event EventHandler StructureChanged;
        public event EventHandler<PropertyHasChangedEventArgs<TimeSpan>> ObservationTimeHasChanged;


        protected virtual void OnObservationTimeHasChanged(TimeSpan old)
        {
            if(ObservationTimeHasChanged != null)
                ObservationTimeHasChanged(this,new PropertyHasChangedEventArgs<TimeSpan>(old,this._observationTime));
        }

        protected virtual void OnChanged()
        {
            if (Changed != null)
                Changed(this, new EventArgs());
        }

        protected virtual void OnStructureChanged()
        {
            if (StructureChanged != null)
                StructureChanged(this, new EventArgs());

            OnChanged();
        }

        protected virtual void OnStoryAdded(StoryBase sb)
        {
            if (sb is StorySplit)
            {
                (sb as StorySplit).TimePointHasChanged += new EventHandler<Mpi.Common.PropertyHasChangedEventArgs<TimeSpan>>(StoryBoard_TimePointChanged);
            }
            if (StoryAdded != null)
                StoryAdded(this, new ItemEventArgs<StoryBase>(sb));
            OnStructureChanged();
        }

        void StoryBoard_TimePointChanged(object sender, Mpi.Common.PropertyHasChangedEventArgs<TimeSpan> e)
        {
            //throw new Exception("The method or operation is not implemented.");
        }

        void StoryBoard_TimePointChanged(object sender, EventArgs e)
        {
            //OnStructureChanged();
        }

        protected virtual void OnStoryRemoved(StoryBase sb)
        {
            if (StoryRemoved != null)
                StoryRemoved(this, new ItemEventArgs<StoryBase>(sb));
            OnStructureChanged();
        }

        void OnStoryNodeRemoved(object sender, NodeEventArgs<StoryBase> e)
        {
            e.AddedNode.Content.StoryBoard = null;
            e.AddedNode.Content.PropertyChanged -= new PropertyChangedEventHandler(Content_PropertyChanged);
            OnStoryRemoved(e.AddedNode.Content);
        }
            

        void OnStoryNodeAdded(object sender, NodeEventArgs<StoryBase> e)
        {
            e.AddedNode.Content.StoryBoard = this;
            e.AddedNode.Content.PropertyChanged += new PropertyChangedEventHandler(Content_PropertyChanged);
            OnStoryAdded(e.AddedNode.Content);
        }

        void Content_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            OnChanged();
        }

        void OnStoryChanged(object sender, EventArgs e)
        {
            OnChanged();
        }



        #endregion

    }
}
